package com.mc.lp.database.service.handler.user;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.springframework.util.CollectionUtils;

import com.mc.lp.database.cache.CacheServiceType;
import com.mc.lp.database.cache.GradesCache;
import com.mc.lp.database.cache.SocialBehaviourCache;
import com.mc.lp.database.entity.type.SchoolGrade;
import com.mc.lp.database.entity.type.StrengthWeaknessType;
import com.mc.lp.database.exception.DataNotFoundException;
import com.mc.lp.database.service.IAttachmentService;
import com.mc.lp.database.service.handler.AbstractFormHandler;
import com.mc.lp.database.service.handler.constant.FormRequestType;
import com.mc.lp.database.service.handler.util.GenericAggregator;
import com.mc.lp.service.MicroCampusEntityService;
import com.mc.lp.service.RecommendationService;
import com.mc.lp.service.SocialBehaviorService;
import com.mc.lp.shared.util.constants.ResponseStatus;
import com.mc.lp.shared.vo.IValueObject;
import com.mc.lp.shared.vo.KeyValue;
import com.mc.lp.shared.vo.RecommendationVO;
import com.mc.lp.shared.vo.SearchCriteriaVO;
import com.mc.lp.shared.vo.ServiceResponse;
import com.mc.lp.shared.vo.SocialBehaviorRecordVO;
import com.mc.lp.shared.vo.user.CommonGridVo;
import com.mc.lp.shared.vo.user.bubble.BubbleRow;
import com.mc.lp.shared.vo.user.bubble.BubbleTable;
import com.mc.lp.shared.vo.user.bubble.BubbleValue;

/*
 * @author aphanda
 * @date Mar 10, 2015
 * @time 9:58:37 PM
 */

public class UserSocialBehaviourDashboardHandler extends AbstractFormHandler<IValueObject, IValueObject> {

	@Resource
	private SocialBehaviorService socialBehaviorService;

	@Resource
	private MicroCampusEntityService microCampusEntityService;

	@Resource
	private RecommendationService recommendationService;

	@Resource
	private IAttachmentService attachmentService;

	@Override
	public HashSet<FormRequestType> getRequestHandlingType() {
		HashSet<FormRequestType> handledRequest = new HashSet<FormRequestType>();
		handledRequest.add(FormRequestType.USER_SOCIAL_BEHAVIOUR_DASHBOARD_OVERALL_GRID);
		handledRequest.add(FormRequestType.USER_SOCIAL_BEHAVIOUR_DASHBOARD_OVERALL_RECOMMENDATION);
		handledRequest.add(FormRequestType.USER_SOCIAL_BEHAVIOUR_DASHBOARD_OVERALL_STRENGTH);
		return handledRequest;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.mc.lp.database.service.handler.AbstractFormHandler#serveRequest(com
	 * .mc.lp.database.service.handler.constant.FormRequestType,
	 * com.mc.lp.shared.vo.IValueObject)
	 */
	@Override
	public IValueObject serveRequest(FormRequestType requestType, IValueObject object) throws Exception {
		switch (requestType) {
		case USER_SOCIAL_BEHAVIOUR_DASHBOARD_OVERALL_GRID:
			return getOverallGrid(requestType, (SearchCriteriaVO) object);
		case USER_SOCIAL_BEHAVIOUR_DASHBOARD_OVERALL_RECOMMENDATION:
			return getRecommendationsForStudent(requestType, (SearchCriteriaVO) object);
		case USER_SOCIAL_BEHAVIOUR_DASHBOARD_OVERALL_STRENGTH:
			return getStrengthAndWeaknessData(requestType, (SearchCriteriaVO) object);
		default:
			return null;
		}
	}

	private IValueObject getStrengthAndWeaknessData(FormRequestType requestType, SearchCriteriaVO object) {
		List<Integer> gradeValueList = getGradesByPageNumAndLimit(object);
		ServiceResponse<BubbleTable> serviceResponse = new ServiceResponse<BubbleTable>();
		if (gradeValueList == null) {
			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
			return serviceResponse;
		}
		
		BubbleTable table = new BubbleTable();
		List<String> gradeListString = new ArrayList<>();
		
		for (Integer gradeId : gradeValueList) {
			gradeListString.add(SchoolGrade.getSchoolGradeName(gradeId));
		}
		table.setxAxis(gradeListString);
		SocialBehaviourCache sociCache = (SocialBehaviourCache) getCacheService().getService(CacheServiceType.SOCIAL_BEHAVIOUR);
		
		List<GenericAggregator> socioBehavList = socialBehaviorService.getStrengthWeaknessByNamedQuery(object.getStudentEntityId(), gradeValueList);
		if (socioBehavList == null || socioBehavList.isEmpty()) {
			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
			return serviceResponse;
		}
		
		Set<Long> allBehaviours = new HashSet<Long>();

		for (GenericAggregator ga : socioBehavList) {
			allBehaviours.add(ga.getKeyIdentifier());
		}

		List<BubbleRow> bubbleRowList = new ArrayList<>();
		for (Long behaviourId : allBehaviours) {

			BubbleRow bubbleRow = new BubbleRow();
			bubbleRow.setName(sociCache.getEntityById(behaviourId).getBehaviour());
			bubbleRow.setColor("#009900");
			List<BubbleValue> bubbleValueList = new ArrayList<>();
			bubbleRow.setValues(bubbleValueList);

			for (Integer gradeId : gradeValueList) {
				BubbleValue value = null;

				for (GenericAggregator ga : socioBehavList) {
					StrengthWeaknessType type = StrengthWeaknessType.getTypeByWeigtage(ga.getWeightage());
					if (gradeId == ga.getGradeId()) {
						if (behaviourId == ga.getKeyIdentifier()) {
							if (type.equals(StrengthWeaknessType.STRENGTH)) {
								value = new BubbleValue(true);
								break;
							} else if (type.equals(StrengthWeaknessType.WEAKNESS)) {
								value = new BubbleValue(false);
								break;
							}else{
								value = new BubbleValue(false, false);
								break;
							}
						}
					}
				}

				if (value == null) {
					value = new BubbleValue(false, false);
				}

				bubbleRow.getValues().add(value);

			}

			bubbleRowList.add(bubbleRow);
		}
		
		
		/*HashMap<Integer, SocialStrengthWeakness> finalResult = new HashMap<>();
		
		//group grades, then takeout aggreegate;
		HashMap<Integer, List<SocialBehaviorRecordVO>> groupByGrade = Group.unique(socioBehavList, new GroupSocialByGrade());
		//now group by social behaviour record because there are multiple terms
		for(Entry<Integer, List<SocialBehaviorRecordVO>> record: groupByGrade.entrySet()){
			 List<SocialBehaviorRecordVO> perGradeList= record.getValue();
			 //group by social behaviour id, here we have all social behaviour per grade
			 HashMap<Long, List<SocialBehaviorRecordVO>> groupBySocialBehaviour = Group.unique(perGradeList, new GroupBySocialBheviour());
			 //now you have per grade all behaviour and per behavior u have all terms
			 for(Entry<Long, List<SocialBehaviorRecordVO>> perBehaviour: groupBySocialBehaviour.entrySet()){
				 	//calculat average rating
				 	int total=0;
				 	int count=0;
				 	int averageWeightage=0;
				 	for (SocialBehaviorRecordVO socialBehaviour: perBehaviour.getValue()) {
				 		if(socialBehaviour.getAttributeWeightage() <= 0){
				 			continue;
				 		}
				 		total+=socialBehaviour.getAttributeWeightage();
				 		count++;
					}
				 	if(count>0 && total>0){
				 		averageWeightage=total/count;
				 	}
				 	//here we have gradeId behaviour id and average rating
				 	if (averageWeightage>0 && averageWeightage > StrengthWeaknessType.STRENGTH.getMinimumWeightage()){
				 		finalResult.put(record.getKey(), new SocialStrengthWeakness(perBehaviour.getKey(),StrengthWeaknessType.STRENGTH));
					}
			 		else if (averageWeightage>0 && averageWeightage <= StrengthWeaknessType.WEAKNESS.getMinimumWeightage()){
			 			finalResult.put(record.getKey(), new SocialStrengthWeakness(perBehaviour.getKey(),StrengthWeaknessType.WEAKNESS));
					}else{
						finalResult.put(record.getKey(), new SocialStrengthWeakness(perBehaviour.getKey(),StrengthWeaknessType.NONE));
					}
			 }
		}
		*/
//		ServiceResponse<CommonGridVo<StrengthWeaknessVo>> serviceResponse = new ServiceResponse<CommonGridVo<StrengthWeaknessVo>>();
//		SocialBehaviourCache sociCache = (SocialBehaviourCache) getCacheService().getService(CacheServiceType.SOCIAL_BEHAVIOUR);
//
//		List<Integer> gradeValueList = getGradesByPageNumAndLimit(object);
//
//		if (gradeValueList == null) {
//			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
//			return serviceResponse;
//		}
//		
//		List<SocialBehaviorRecordVO> socioBehavList = socialBehaviorService.getSocialBehavioursByGrades(object.getStudentEntityId(), gradeValueList);
//		if (socioBehavList == null || socioBehavList.isEmpty()) {
//			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
//			return serviceResponse;
//		}
//		
//		
//		TreeMap<Integer, List<SocialBehaviorRecordVO>> extraAcademicViewMap = new TreeMap<Integer, List<SocialBehaviorRecordVO>>();
//		// group extra academic based on grades.
//		if (!CollectionUtils.isEmpty(socioBehavList)) {
//			for (SocialBehaviorRecordVO record : socioBehavList) {
//				List<SocialBehaviorRecordVO> existingRecord = extraAcademicViewMap.get(record.getGradeId());
//				// no record found add
//				if (CollectionUtils.isEmpty(existingRecord)) {
//					existingRecord = new ArrayList<SocialBehaviorRecordVO>();
//					existingRecord.add(record);
//					extraAcademicViewMap.put(record.getGradeId(), existingRecord);
//				} else {
//					existingRecord.add(record);
//					extraAcademicViewMap.put(record.getGradeId(), existingRecord);
//				}
//			}
//		}
//
//		// convert to UI Vo
//		CommonGridVo<StrengthWeaknessVo> commonGridVo = new CommonGridVo<StrengthWeaknessVo>();
//		List<KeyValue> gradeList = new ArrayList<KeyValue>();
//
//		if (!CollectionUtils.isEmpty(extraAcademicViewMap)) {
//			for (Entry<Integer, List<SocialBehaviorRecordVO>> entry : extraAcademicViewMap.entrySet()) {
//				Integer gradeId = entry.getKey();
//				if (gradeId != null) {
//
//					ArrayList<KeyValue> strength = new ArrayList<KeyValue>();
//					ArrayList<KeyValue> weakness = new ArrayList<KeyValue>();
//					// calculate strength and weakness and add to respective
//					// list.
//					for (SocialBehaviorRecordVO socioVo : entry.getValue()) {
//						if (socioVo.getAttributeWeightage() > StrengthWeaknessType.STRENGTH.getMinimumWeightage()) {
//							strength.add(new KeyValue(sociCache.getEntityById(socioVo.getSocialBehaviourId()).getBehaviour(), socioVo.getRemarks()));
//						} else if (socioVo.getAttributeWeightage() > 0 && socioVo.getAttributeWeightage() <= StrengthWeaknessType.WEAKNESS.getMinimumWeightage()) {
//							weakness.add(new KeyValue(sociCache.getEntityById(socioVo.getSocialBehaviourId()).getBehaviour(), socioVo.getRemarks()));
//						}
//					}
//
//					StrengthWeaknessVo strengthWeaknessVo = new StrengthWeaknessVo();
//					strengthWeaknessVo.setStrength(strength);
//					strengthWeaknessVo.setWeakness(weakness);// in this
//																// particular
//																// case we dont
//																// have weakness
//					gradeList.add(new KeyValue(SchoolGrade.getSchoolGradeName(gradeId), strengthWeaknessVo));
//				}
//			}
//		}
//
//		commonGridVo.setGradeList(gradeList);
//		serviceResponse.setStatus(ResponseStatus.SUCCESS);
//		serviceResponse.setResult(Arrays.asList(commonGridVo));
//		return serviceResponse;
		// AP BLOCKER
				//ServiceResponse<BubbleTable> serviceResponse = new ServiceResponse<BubbleTable>();
				//BubbleTable table = new BubbleTable();
				
				
				//values should be of equal count as in xAxis;
				//if anygiven extra activity record in student career then make entry here otherwise leave it.
				
				/*BubbleRow row1= new BubbleRow();
				row1.setName("Polite");
				row1.setColor("#009900");
				row1.setValues(Arrays.asList(new BubbleValue(true),new BubbleValue(false),new BubbleValue(true)));
				
				
				BubbleRow row2= new BubbleRow();
				row2.setName("Naughty");
				row2.setColor("#CC0000");
				row2.setValues(Arrays.asList(new BubbleValue(true),new BubbleValue(false),new BubbleValue(false,false)));
				
				
				BubbleRow row3= new BubbleRow();
				row3.setName("Friendly");
				row3.setColor("#000066");
				row3.setValues(Arrays.asList(new BubbleValue(true),new BubbleValue(true),new BubbleValue(true)));
				*/
				//table.setRows(Arrays.asList(row1,row2,row3));	
				table.setRows(bubbleRowList);
				serviceResponse.setStatus(ResponseStatus.SUCCESS);
				serviceResponse.setResult(Arrays.asList(table));
				return serviceResponse;
	}

	private IValueObject getRecommendationsForStudent(FormRequestType requestType, SearchCriteriaVO object) {
		ServiceResponse<RecommendationVO> serviceResponse = new ServiceResponse<RecommendationVO>();
		List<RecommendationVO> recommendationVOS;
		try {
			recommendationVOS = recommendationService.getRecommendationBySearchCriteria(object);
			if (recommendationVOS == null || recommendationVOS.isEmpty()) {
				serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
				return serviceResponse;
			}
			serviceResponse.setResult(recommendationVOS);
			serviceResponse.setExtraInfo(new KeyValue("class", SchoolGrade.getSchoolGradeName(object.getGradeId()))); // send
																														// recommendation
																														// year
																														// along
																														// with
																														// extra
																														// into
			serviceResponse.setStatus(ResponseStatus.SUCCESS);
		} catch (DataNotFoundException e) {
			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
		} catch (Exception e) {
			serviceResponse.setStatus(ResponseStatus.FAILED);
		}
		return serviceResponse;
	}

	private IValueObject getOverallGrid(FormRequestType requestType, SearchCriteriaVO object) {

		ServiceResponse<CommonGridVo<SocialBehaviorRecordVO>> serviceResponse = new ServiceResponse<CommonGridVo<SocialBehaviorRecordVO>>();
		List<Integer> gradeValueList = getGradesByPageNumAndLimit(object);

		if (gradeValueList == null) {
			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
			return serviceResponse;
		}
		List<SocialBehaviorRecordVO> socioBehavList = socialBehaviorService.getSocialBehavioursByGrades(object.getStudentEntityId(), gradeValueList);
		if (socioBehavList == null || socioBehavList.isEmpty()) {
			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
			return serviceResponse;
		}
		// DV BP-1 Please use socioBehav list accordingly in SB tab

		TreeMap<Integer, List<SocialBehaviorRecordVO>> SoBehavViewMap = new TreeMap<Integer, List<SocialBehaviorRecordVO>>();
		// group extra academic based on grades.
		if (!CollectionUtils.isEmpty(socioBehavList)) {
			for (SocialBehaviorRecordVO record : socioBehavList) {
				List<SocialBehaviorRecordVO> existingRecord = SoBehavViewMap.get(record.getGradeId());
				// no record found add
				if (CollectionUtils.isEmpty(existingRecord)) {
					existingRecord = new ArrayList<SocialBehaviorRecordVO>();
					existingRecord.add(record);
					SoBehavViewMap.put(record.getGradeId(), existingRecord);
				} else {
					existingRecord.add(record);
					SoBehavViewMap.put(record.getGradeId(), existingRecord);
				}
			}
		}
		// convert to UI Vo
		CommonGridVo<SocialBehaviorRecordVO> commonGridVo = new CommonGridVo<SocialBehaviorRecordVO>();
		List<KeyValue> gradeList = new ArrayList<KeyValue>();

		if (!CollectionUtils.isEmpty(SoBehavViewMap))
			for (Entry<Integer, List<SocialBehaviorRecordVO>> entry : SoBehavViewMap.entrySet()) {
				Integer gradeId = entry.getKey();
				if (gradeId != null)
					gradeList.add(new KeyValue(SchoolGrade.getSchoolGradeName(gradeId), entry.getValue()));
			}

		commonGridVo.setGradeList(gradeList);
		commonGridVo.setObjects(socioBehavList);

		serviceResponse.setStatus(ResponseStatus.SUCCESS);
		serviceResponse.setResult(Arrays.asList(commonGridVo));

		return serviceResponse;

	}
}
